package com.carleasoft.mps.adu.business.basicsInfo.service.impl;

import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carleasoft.mps.adu.business.basicsInfo.bean.entity.AuthorityUserBasicInfo;
import com.carleasoft.mps.adu.business.basicsInfo.bean.po.*;
import com.carleasoft.mps.adu.business.basicsInfo.bean.vo.*;
import com.carleasoft.mps.adu.business.basicsInfo.dao.AuthorityUserBasicInfoMapper;
import com.carleasoft.mps.adu.business.basicsInfo.excel.ConvertTemplatePath;
import com.carleasoft.mps.adu.business.basicsInfo.excel.ExcelUtils;
import com.carleasoft.mps.adu.business.basicsInfo.service.AuthorityUserBasicInfoService;
import com.carleasoft.mps.adu.business.dept.bean.entity.DeptEntity;
import com.carleasoft.mps.adu.business.dept.service.DeptService;
import com.carleasoft.mps.adu.business.user.bean.entity.AuthorityUserDept;
import com.carleasoft.mps.adu.business.user.bean.entity.AuthorityUserEntity;
import com.carleasoft.mps.adu.business.user.bean.entity.AuthorityUserTypeEntity;
import com.carleasoft.mps.adu.business.user.bean.po.AuthorityUserPo;
import com.carleasoft.mps.adu.business.user.bean.po.UserDeptPo;
import com.carleasoft.mps.adu.business.user.service.AuthorityUserDeptService;
import com.carleasoft.mps.adu.business.user.service.AuthorityUserService;
import com.carleasoft.mps.adu.business.user.service.AuthorityUserTypeService;
import com.carleasoft.mps.adu.common.constants.BusinessErrorEnum;
import com.carleasoft.mps.core.exceptions.BusinessException;
import com.carleasoft.mps.core.result.R;
import com.carleasoft.mps.core.user.ThreadUserContext;
import com.carleasoft.mps.core.user.UserCacheData;
import com.carleasoft.mps.core.utils.ConvertUtils;
import com.carleasoft.mps.core.utils.IBeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: yangHao
 * @createDate:2023/6/5
 * @description:
 */
@Service
public class AuthorityUserBasicInfoServiceImpl extends ServiceImpl<AuthorityUserBasicInfoMapper, AuthorityUserBasicInfo> implements AuthorityUserBasicInfoService {
    @Autowired
    private AuthorityUserService authorityUserService;
    @Autowired
    private AuthorityUserTypeService userTypeService;
    @Autowired
    private AuthorityUserDeptService authorityUserDeptService;

    @Autowired
    private DeptService deptService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveUser(AuthorityUserBasicInfoPo authorityUserBasicInfoPo) {
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        AuthorityUserPo authorityUserPo = ConvertUtils.sourceToTarget(authorityUserBasicInfoPo, AuthorityUserPo.class);
        authorityUserBasicInfoPo.setUserTypeCode("0003");
        List<UserDeptPo> userDeptPos = new ArrayList<>();
        if(CollUtil.isNotEmpty(authorityUserBasicInfoPo.getDeptCodes())){
            for (DeptAndPositionPo deptCode : authorityUserBasicInfoPo.getDeptCodes()) {
                UserDeptPo userDeptPo = new UserDeptPo();
                userDeptPo.setDeptCode(deptCode.getDeptCode());
                userDeptPos.add(userDeptPo);
            }
        }
        authorityUserPo.setUserDeptPos(userDeptPos);
        String userTypeCode = userTypeService.getOne(Wrappers.<AuthorityUserTypeEntity>lambdaQuery().eq(AuthorityUserTypeEntity::getUserTypeNumber, authorityUserBasicInfoPo.getUserTypeCode())).getUserTypeCode();
        authorityUserPo.setUserTypeCode(userTypeCode);
        AuthorityUserEntity authorityUserEntity = authorityUserService.addUser(authorityUserPo);
        AuthorityUserBasicInfo basicInfoEntity = ConvertUtils.sourceToTarget(authorityUserBasicInfoPo, AuthorityUserBasicInfo.class);
        basicInfoEntity.setUserCode(authorityUserEntity.getUserCode());
        basicInfoEntity.setCreateTime(LocalDateTime.now());
        basicInfoEntity.setCreatePersonCode(user.getUserCode());
        basicInfoEntity.setCreatePersonName(user.getUserName());
        basicInfoEntity.setUpdateTime(LocalDateTime.now());
        basicInfoEntity.setUpdatePersonCode(user.getUserCode());
        basicInfoEntity.setUpdatePersonName(user.getUserName());
//        basicInfoEntity.setPolitical(Integer.parseInt(authorityUserBasicInfoPo.getPolitical()));
        return this.save(basicInfoEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUser(AuthorityUserBasicInfoPo authorityUserBasicInfoPo) {
        boolean isOk = false;
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        AuthorityUserPo authorityUserPo = ConvertUtils.sourceToTarget(authorityUserBasicInfoPo, AuthorityUserPo.class);
        authorityUserBasicInfoPo.setUserTypeCode("0003");
        List<UserDeptPo> userDeptPos = new ArrayList<>();
        for (DeptAndPositionPo deptCode : authorityUserBasicInfoPo.getDeptCodes()) {
            UserDeptPo userDeptPo = new UserDeptPo();
            userDeptPo.setDeptCode(deptCode.getDeptCode());
            userDeptPos.add(userDeptPo);
        }
        authorityUserPo.setUserDeptPos(userDeptPos);
        this.authorityUserService.updateUser(authorityUserPo);
        AuthorityUserBasicInfo basicInfoEntity = this.getOne(Wrappers.<AuthorityUserBasicInfo>lambdaQuery()
                .eq(AuthorityUserBasicInfo::getUserCode, authorityUserBasicInfoPo.getUserCode()));
        if (Objects.nonNull(basicInfoEntity)) {
            BeanUtil.copyProperties(authorityUserBasicInfoPo, basicInfoEntity);
            basicInfoEntity.setUpdateTime(LocalDateTime.now());
            basicInfoEntity.setUpdatePersonCode(user.getUserCode());
            basicInfoEntity.setUpdatePersonName(user.getUserName());
            isOk = this.updateById(basicInfoEntity);
        }
        return isOk;
    }

    @Override
    public Page<AuthorityUserBasicInfoVo> pageQuery(Page page, AuthorityUserBasicInfoPo authorityUserBasicInfoPo) {
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        QueryWrapper<AuthorityUserBasicInfo> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("USER_CODE", user.getUserCode());
        if (StrUtil.isNotBlank(authorityUserBasicInfoPo.getKeyword())) {
            queryWrapper.like("USER_NAME", authorityUserBasicInfoPo.getKeyword());
        }
        queryWrapper.orderByDesc("UPDATE_TIME");
        return this.page(page, queryWrapper);
    }

    @Override
    public AuthorityUserInfoVo selectById(String userCode) {
        AuthorityUserBasicInfo authorityUserBasicInfo = this.getOne(Wrappers.<AuthorityUserBasicInfo>lambdaQuery()
                .eq(AuthorityUserBasicInfo::getUserCode, userCode));
        if (Objects.nonNull(authorityUserBasicInfo)) {
            List<AuthorityUserDept> authorityUserDepts = authorityUserDeptService.list(Wrappers.<AuthorityUserDept>lambdaQuery()
                    .eq(AuthorityUserDept::getUserCode, authorityUserBasicInfo.getUserCode()));
            List<DeptAndPositionPo> deptAndPositionPos = new ArrayList<>();
            for (AuthorityUserDept authorityUserDept : authorityUserDepts) {
                DeptAndPositionPo deptAndPositionPo = new DeptAndPositionPo();
                deptAndPositionPo.setDeptCode(authorityUserDept.getDeptCode());
                deptAndPositionPos.add(deptAndPositionPo);
            }
            authorityUserBasicInfo.setDeptCodes(deptAndPositionPos);
            AuthorityUserEntity authorityUserServiceOne = authorityUserService.getOne(Wrappers.<AuthorityUserEntity>lambdaQuery()
                    .eq(AuthorityUserEntity::getUserCode, authorityUserBasicInfo.getUserCode()));
            authorityUserBasicInfo.setUserNumber(authorityUserServiceOne.getUserNumber());
            AuthorityUserInfoVo authorityUserInfoVo = BeanUtil.copyProperties(authorityUserBasicInfo, AuthorityUserInfoVo.class);
            if (authorityUserBasicInfo.getSkill()!=null){
                authorityUserInfoVo.setSkill(authorityUserBasicInfo.getSkill().toString());
            }
            if (authorityUserInfoVo.getCommand()!=null){
                authorityUserInfoVo.setCommand(authorityUserBasicInfo.getCommand().toString());
            }
            if (CollUtil.isNotEmpty(authorityUserBasicInfo.getDeptCodes())){
                List<DeptAndPositionPo> deptAndPositionPoList = authorityUserBasicInfo.getDeptCodes();
                Set<String> deptCodes = deptAndPositionPoList.stream().map(DeptAndPositionPo::getDeptCode).collect(Collectors.toSet());
                List<DeptEntity> deptEntities = deptService.list(Wrappers.<DeptEntity>lambdaQuery()
                        .in(DeptEntity::getDeptCode, deptCodes));
                StringBuilder deptName = new StringBuilder();
                for (int i = 0; i < deptEntities.size(); i++) {
                    DeptEntity deptEntity = deptEntities.get(i);
                    if (i == deptEntities.size() - 1) {
                        deptName.append(deptEntity.getDeptName());
                    } else {
                        deptName.append(deptEntity.getDeptName()).append("、");
                    }
                }
                authorityUserInfoVo.setDeptName(deptName.toString());
            }else {
                AuthorityUserDept authorityUserDept = new AuthorityUserDept();
                authorityUserDept.setUserCode(authorityUserBasicInfo.getUserCode());
                authorityUserDept.setDeptCode("1669882424827342849");
                authorityUserDept.setSort(1);
                authorityUserDept.setSortDate(1L);
                authorityUserDeptService.save(authorityUserDept);
            }

            authorityUserInfoVo.setType(2);
            return authorityUserInfoVo;
        } else {
            AuthorityUserEntity authorityUserServiceOne = authorityUserService.getOne(Wrappers.<AuthorityUserEntity>lambdaQuery()
                    .eq(AuthorityUserEntity::getUserCode, userCode));
            AuthorityUserInfoVo authorityUserInfoVo = BeanUtil.copyProperties(authorityUserServiceOne, AuthorityUserInfoVo.class);
            authorityUserInfoVo.setType(1);
            return authorityUserInfoVo;
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(AuthorityUserBasicInfoPo authorityUserBasicInfoPo) {
        boolean isOk = false;
        AuthorityUserPo authorityUserPo = BeanUtil.copyProperties(authorityUserBasicInfoPo, AuthorityUserPo.class);
        authorityUserPo.setUserCode(authorityUserBasicInfoPo.getUserCode());
        isOk = authorityUserService.deleteUser(authorityUserPo);
        isOk = this.remove(Wrappers.<AuthorityUserBasicInfo>lambdaQuery()
                .eq(AuthorityUserBasicInfo::getUserCode, authorityUserBasicInfoPo.getUserCode()));
        return isOk;
    }

    @Override
    public void excel(HttpServletResponse response) {
        Map<String, Object> map = new HashMap<>();
        String path = "\\template\\userExcelTemplate.xls";
        TemplateExportParams templatePath = new TemplateExportParams(ConvertTemplatePath.convertTemplatePath(path));
        try {
            ExcelUtils.exportExcel(templatePath, map, "用户下载模块", response);
        } catch (IOException e) {

        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean importUserExcel(MultipartFile file) {
        List<UserInfoExcelVo> list = null;
        boolean isOK = false;
        try {
            list = ExcelUtils.importExcel(file, UserInfoExcelVo.class);
            list = list.stream().filter(i -> i.getUserName() != null).collect(Collectors.toList());
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String, List<UserInfoExcelVo>> map = list.stream().collect(Collectors.groupingBy(UserInfoExcelVo::getUserNumber));
        List<String> userNumbers = list.stream().map(UserInfoExcelVo::getUserNumber).collect(Collectors.toList());
        if (map.size() != userNumbers.size()) {
            throw new BusinessException(BusinessErrorEnum.DUPLICATE_USER_RNUMBER);
        }
        List<AuthorityUserEntity> authorityUserEntities = authorityUserService.list(Wrappers.<AuthorityUserEntity>lambdaQuery()
                .in(AuthorityUserEntity::getUserNumber, userNumbers));
        if (CollUtil.isNotEmpty(authorityUserEntities)) {
            String aaa = "编号已经存在了，存在的编号有:";
            StringBuilder stringBuilder = new StringBuilder();
            for (AuthorityUserEntity authorityUserEntity : authorityUserEntities) {
                stringBuilder.append(authorityUserEntity).append("、");
            }
            throw new BusinessException("10086", aaa + stringBuilder);
        }
        for (UserInfoExcelVo userInfoExcelVo : list) {
            AuthorityUserBasicInfoPo authorityUserBasicInfoPo = BeanUtil.copyProperties(userInfoExcelVo, AuthorityUserBasicInfoPo.class);
            isOK = this.saveUser(authorityUserBasicInfoPo);
        }

        return isOK;
    }

    @Override
    public void excelExam(ExcelPo excelPo, HttpServletResponse response) {
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        Integer type = excelPo.getType();
        String path = null;
        String fileName = null;
        switch (type) {
            case 1:
                path = "\\template\\examExcelTemplateOne.xls";
                fileName = "花名册";
                break;
            case 2:
                path = "\\template\\contentExcelOne.xls";
                fileName = "考核内容";
                break;
            case 3:
                path = "\\template\\planExcelOne.xls";
                fileName = "训练计划";
                break;
            case 4:
                path = "\\template\\carImportOne.xls";
                fileName = "报车用车";
                break;
            case 5:
                path = "\\template\\repairsExcel.xls";
                fileName = "营房报修";
                break;
            case 6:
                path = "\\template\\equipmentExcel.xls";
                fileName = "器材申请";
                break;
            case 7:
                path = "\\template\\vehicleExcel.xls";
                fileName = "车辆报修";
                break;
            case 8:
                path = "\\template\\userDynamicTemplate.xls";
                fileName = "人员动态";
                break;
            case 9:
                path = "\\template\\userVacationTemplate.xls";
                fileName = "人员休假";
                break;
            case 10:
                path = "\\template\\staggerHolidaysTemplate.xls";
                fileName = "人员轮休";
                break;
        }
        Map<String, Object> map = new HashMap<>();
        TemplateExportParams templatePath = new TemplateExportParams(ConvertTemplatePath.convertTemplatePath(path));
        try {
            ExcelUtils.exportExcel(templatePath, map, fileName, response);
        } catch (IOException e) {

        }
    }

    @Override
    public List<TargetItemPo> importExcel(MultipartFile file) {
        List<TargetItemPo> list = null;
        try {
            list = ExcelUtils.importExcel(file, TargetItemPo.class);
            list = list.stream().filter(i -> i.getName() != null).collect(Collectors.toList());
        } catch (IOException e) {
            e.printStackTrace();
        }
        Set<String> deptNames = list.stream().map(TargetItemPo::getDeptName).collect(Collectors.toSet());
        Map<String, List<TargetItemPo>> map = list.stream().collect(Collectors.groupingBy(TargetItemPo::getDeptName));
        List<TargetItemPo> poList = new ArrayList<>();
        for (String deptName : deptNames) {
            List<TargetItemPo> targetItemPos = map.get(deptName);
            List<String> userNames = targetItemPos.stream().map(TargetItemPo::getName).collect(Collectors.toList());
            List<TargetItemPo> targetItemPoList = this.getBaseMapper().userInfo(deptName, userNames);
            poList.addAll(targetItemPoList);
        }
        return poList;
    }

    @Override
    public Page<UserInfoCountVo> userInfoCount(Page page, UserInfoCountPo userInfoCountPo) {
        IBeanUtil.paramVerify(userInfoCountPo, "current", "size");
        Page<UserInfoCountVo> userInfoCountVoPage = new Page<>();
        if (StrUtil.isNotBlank(userInfoCountPo.getResource())) {
            if (userInfoCountPo.getResource().equals("专业技术能手")) {
                int type = 0;
                if (userInfoCountPo.getResourceName().equals("技术能手")) {
                    type = 1;
                } else {
                    type = 2;
                }
                userInfoCountPo.setType(type);
                List<String> userCodes = this.getBaseMapper().technology(userInfoCountPo);
                if (CollUtil.isNotEmpty(userCodes)) {
                    userInfoCountPo.setUserCodes(userCodes);
                    userInfoCountVoPage = this.getBaseMapper().userInfoCount(page, userInfoCountPo);
                }
            }
            if (userInfoCountPo.getResource().equals("创破记录")) {
                int type = 0;
                if (userInfoCountPo.getResourceName().equals("有创破记录")) {
                    type = 1;
                } else {
                    type = 2;
                }
                userInfoCountPo.setTypeOne(type);
                List<String> userCodes = this.getBaseMapper().technology(userInfoCountPo);
                if (CollUtil.isNotEmpty(userCodes)) {
                    userInfoCountPo.setUserCodes(userCodes);
                    userInfoCountVoPage = this.getBaseMapper().userInfoCount(page, userInfoCountPo);
                }
            }

            if (userInfoCountPo.getResource().equals("年龄统计")) {
                String resourceName = userInfoCountPo.getResourceName();
                if (resourceName.contains("~")) {
                    String[] split = resourceName.split("~");
                    userInfoCountPo.setAgeStart(Integer.parseInt(split[0]));
                    userInfoCountPo.setAgeEnd(Integer.parseInt(split[1]));
                } else {
                    userInfoCountPo.setAgeStart(65);
                }
                userInfoCountVoPage = this.getBaseMapper().userInfoCount(page, userInfoCountPo);
            }
            if (userInfoCountPo.getResource().equals("职业技能鉴定")) {
                String resourceName = userInfoCountPo.getResourceName();
                String code = this.getBaseMapper().dict(resourceName,userInfoCountPo.getResource());
                userInfoCountPo.setSkill(code);
                userInfoCountVoPage = this.getBaseMapper().userInfoCount(page, userInfoCountPo);
            }
            if (userInfoCountPo.getResource().equals("学历统计")) {
                String resourceName = userInfoCountPo.getResourceName();
                List<Integer> integers = new ArrayList<>();
                if (resourceName.equals("初中及以下")) {
                    integers.add(1);
                    integers.add(2);
                }else if (resourceName.equals("高中/中专/技校")){
                    integers.add(3);
                }else if (resourceName.equals("专科")){
                    integers.add(4);
                }else if (resourceName.equals("本科")){
                    integers.add(5);
                }else if (resourceName.equals("硕士研究生")){
                    integers.add(6);
                }else if (resourceName.equals("博士研究生")){
                    integers.add(7);
                }
                userInfoCountPo.setEducationS(integers);
                userInfoCountVoPage = this.getBaseMapper().userInfoCount(page, userInfoCountPo);
            }
            if (userInfoCountPo.getResource().equals("指挥技能")){
                String resourceName = userInfoCountPo.getResourceName();
                String code = this.getBaseMapper().dict(resourceName,userInfoCountPo.getResource());
                userInfoCountPo.setCommand(code);
                userInfoCountVoPage = this.getBaseMapper().userInfoCount(page, userInfoCountPo);
            }
            if (userInfoCountPo.getResource().equals("婚姻状况统计")){
                String resourceName = userInfoCountPo.getResourceName();
                if (resourceName.equals("已婚")) {
                    userInfoCountPo.setMarital(2);
                }else if (resourceName.equals("未婚")){
                    userInfoCountPo.setMarital(1);
                }else if (resourceName.equals("离异")){
                    userInfoCountPo.setMarital(3);
                }else if (resourceName.equals("丧偶")){
                    userInfoCountPo.setMarital(4);
                }
                userInfoCountVoPage = this.getBaseMapper().userInfoCount(page, userInfoCountPo);
            }


        } else {
            userInfoCountVoPage = this.getBaseMapper().userInfoCount(page, userInfoCountPo);
        }
        if (CollUtil.isNotEmpty(userInfoCountVoPage.getRecords())) {
            Set<String> userCodes = userInfoCountVoPage.getRecords().stream().map(UserInfoCountVo::getUserCode).filter(Objects::nonNull).collect(Collectors.toSet());
            List<UserInfoVos> userInfoVos = this.getBaseMapper().userCodes(userCodes);
            Map<String, List<UserInfoVos>> listMap = new HashMap<>();
            if (CollUtil.isNotEmpty(userInfoVos)) {
                listMap = userInfoVos.stream().collect(Collectors.groupingBy(UserInfoVos::getUserCode));
            }
            for (UserInfoCountVo record : userInfoCountVoPage.getRecords()) {
                if (listMap.containsKey(record.getUserCode())) {
                    StringBuilder deptName = new StringBuilder();
                    List<UserInfoVos> infoVos = listMap.get(record.getUserCode());
                    for (int i1 = 0; i1 < infoVos.size(); i1++) {
                        UserInfoVos infoVos1 = infoVos.get(i1);
                        if (i1 == infoVos.size() - 1) {
                            deptName.append(infoVos1.getDeptName());
                        } else {
                            deptName.append(infoVos1.getDeptName()).append("、");
                        }

                    }
                    record.setDeptName(deptName.toString());
                }
            }

        }

        return userInfoCountVoPage;
    }

    @Override
    public Integer userSubmitFlagById() {
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        AuthorityUserBasicInfo authorityUserBasicInfo = this.getOne(Wrappers.<AuthorityUserBasicInfo>lambdaQuery()
                .eq(AuthorityUserBasicInfo::getUserCode, user.getUserCode()));
        if(ObjectUtils.isEmpty(authorityUserBasicInfo)){
            return 0;
        }
        return authorityUserBasicInfo.getUserSubmitFlag();
    }
}
